<?php

namespace App\Http\Controllers;

use App\Enums\GameStatus;
use App\Helper\ApiResponseHelper;
use App\Helper\GameMatchBind;
use App\Http\Requests\GameMatchWinRequest;
use App\Http\Requests\GameMatchEditRequest;
use App\Http\Requests\GameMatchRequest;
use App\Http\Requests\GameRequest;
use App\Http\Resources\GameMatchResource;
use App\Http\Resources\GameResource;
use App\Models\Game;
use App\Models\GameMatch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class GameController extends Controller
{
    public function getGames()
    {
        $games = Game::latest()->with([
            'matches.leftMember',
            'matches.rightMember',
            'matches.winMember',
            'users.member'
        ])->paginate();

        return GameResource::collection($games);
    }

    public function getGame(Game $game)
    {
        return new GameResource($this->refreshGame($game));
    }

    public function create(GameRequest $request)
    {
        $game = Game::create(array_merge(['status' => GameStatus::Processing->value], $request->only(
            'name', 'game_start_date', 'company_name', 'address', 'detail',
        )));

        return new GameResource($game);
    }

    public function edit(Game $game, GameRequest $request)
    {
        $game->update($request->only(
            'name', 'game_start_date', 'company_name', 'address', 'detail',
        ));
        $game->refresh();

        return new GameResource($game);
    }

    public function initMatch(Game $game, GameMatchRequest $request)
    {
        $memberIds = $request->input('member_ids');

        if ($game->matches()->count() != 0)
            return ApiResponseHelper::json([], 400, '比赛已初始化过，请勿重复初始化');

        DB::transaction(function () use ($game, $memberIds) {

            //先创建sign user
            $this->checkAndInsertSignUser($game, $memberIds);

            //打乱member id
            shuffle($memberIds);

            $matches = $this->createMatch32($game);

            // 分配比赛
            for ($i = 1; $i <= 16; $i++) {

                foreach ($matches as $match) {

                    if ($match->sort == $i) {

                        $match->left_member_id = $memberIds[$i*2-1-1];
                        $match->right_member_id = $memberIds[$i*2-1];
                        $match->save();
                        break;
                    }
                }
            }
        });

        return ApiResponseHelper::json([]);
    }

    public function editMatch(Game $game, GameMatch $gameMatch, GameMatchEditRequest $request)
    {
        $gameMatch->update($request->only([
            'start_at', 'screen'
        ]));

        return new GameMatchResource($gameMatch);
    }

    public function winMatch(Game $game, GameMatch $gameMatch, GameMatchWinRequest $request)
    {
        $memberId = $request->input('member_id');

        if (!empty($gameMatch->win_member_id))
            return ApiResponseHelper::json([], 400, '请勿重复操作，每场只允许获胜一次');

        if ($gameMatch->left_member_id != $memberId && $gameMatch->right_member_id != $memberId)
            return ApiResponseHelper::json([], 400, 'member id错误');

        DB::transaction(function () use ($game, $gameMatch, $memberId) {

            $gameMatch->win_member_id = $memberId;
            $gameMatch->save();

            $sign = $game->users()->where('member_id', $memberId)->first();
            $sign->point += 100;
            $sign->save();

            $this->match32AutoNext($gameMatch);
        });

        return ApiResponseHelper::json([]);
    }

    private function match32AutoNext(GameMatch $gameMatch)
    {
        $next = GameMatchBind::match32Bind()["$gameMatch->sort"] ?? null;

        if (empty($next))
            return;

        $lostUserId = $gameMatch->left_member_id;

        if ($lostUserId == $gameMatch->win_user_id)
            $lostUserId = $gameMatch->right_member_id;

        // 安排胜者
        $nextWinMatch = GameMatch::where([
            'game_id' => $gameMatch->game_id,
            'sort' => $next['win'],
            'type' => 'formal'
        ])->first();

        if (empty($nextWinMatch->left_member_id))
            $nextWinMatch->left_member_id = $gameMatch->win_user_id;
        else
            $nextWinMatch->right_member_id = $gameMatch->win_user_id;

        $nextWinMatch->save();

        //安排败者
        if (!empty($next['lost'])) {

            $nextLostMatch = GameMatch::where([
                'game_id' => $gameMatch->game_id,
                'sort' => $next['lost'],
                'type' => 'formal'
            ])->first();

            if (empty($nextLostMatch->left_member_id))
                $nextLostMatch->left_member_id = $lostUserId;
            else
                $nextLostMatch->right_member_id = $lostUserId;

            //下一场是败者空场
            if ($nextLostMatch->loss == 'y') {

                $nextNext = GameMatchBind::match32Bind()[$nextLostMatch->sort];

                $nextNextMatch = GameMatch::where([
                    'game_id' => $gameMatch->game_id,
                    'sort' => $nextNext['win'],
                    'type' => 'formal'
                ])->first();

                if (empty($nextNextMatch->left_member_id))
                    $nextNextMatch->left_member_id = $lostUserId;
                else
                    $nextNextMatch->right_member_id = $lostUserId;

                $nextNextMatch->save();

                $nextLostMatch->win_user_id = $nextLostMatch->left_member_id ?? $nextLostMatch->right_member_id;
            }

            $nextLostMatch->save();
        }
    }

    private function createMatch32(Game $game)
    {
        $games = [];
        for ($i = 1; $i <= 62; $i++) {

            $games[] = GameMatch::create([
                'type' => 'formal',
                'start_at' => date('Y-m-d H:i:s'),
                'screen' => '',
                'sort' => $i,
                'game_id' => $game->id
            ]);
        }

        //loss matches
        $lossMatchArr = [
            '25', '26', '27', '28', '29', '30', '31', '32',
            '41', '42', '43', '44',
            '49', '50', '55'
        ];

        foreach ($lossMatchArr as $lossSort) {

            $games[] = GameMatch::create([
                'type' => 'formal',
                'start_at' => date('Y-m-d H:i:s'),
                'screen' => '',
                'sort' => $lossSort.'L',
                'game_id' => $game->id,
                'loss' => 'y'
            ]);
        }

        return $games;
    }

    private function refreshGame(Game $game)
    {
        return Game::with([
            'matches.leftMember',
            'matches.rightMember',
            'matches.winMember',
            'users.member'
        ])->find($game->id);
    }
    private function checkAndInsertSignUser(Game $game, $memberIds)
    {
        foreach ($memberIds as $id) {

            if (empty($game->users()->where('member_id', $id)->first()))
                $game->users()->create([
                    'member_id' => $id,
                    'point' => 0,
                    'is_checked' => true
                ]);
        }
    }
}
